<style scoped>

    .m-b-none {
        margin-bottom: 0;
    }

    .access-key {
        border: 1px solid #cacaca;
        border-radius: 3px;
        padding: 10px 10px 0;
        background-color: #fafafa;
    }

    pre {
        font-size: 12px;
        word-wrap: break-word;
        white-space: pre-wrap;
    }
</style>

<template>
  <div>
    <div>
      <div class="panel panel-default">
        <div class="panel-heading">
          <div style="display: flex; justify-content: space-between; align-items: center;">
            <span>
              {{ $t('settings.api_personal_access_tokens') }}
            </span>

            <a class="btn" href="" @click.prevent="showCreateTokenForm">
              {{ $t('settings.api_token_create_new') }}
            </a>
          </div>
        </div>

        <div class="panel-body">
          <!-- No Tokens Notice -->
          <p v-if="tokens.length === 0" class="m-b-none">
            {{ $t('settings.api_token_not_created') }}
          </p>

          <!-- Personal Access Tokens -->
          <table v-else class="table table-borderless m-b-none">
            <thead>
              <tr>
                <th scope="col">
                  {{ $t('settings.api_token_name') }}
                </th>
                <th scope="col"></th>
              </tr>
            </thead>

            <tbody>
              <tr v-for="token in tokens" :key="token.id">
                <!-- Client Name -->
                <td style="vertical-align: middle;">
                  {{ token.name }}
                </td>

                <!-- Delete Button -->
                <td style="vertical-align: middle;">
                  <a class="action-link text-danger" href="" @click.prevent="revoke(token)">
                    {{ $t('settings.api_token_delete') }}
                  </a>
                </td>
              </tr>
            </tbody>
          </table>
        </div>
      </div>
    </div>

    <!-- Create Token Modal -->
    <div id="modal-create-token" class="modal fade" tabindex="-1" role="dialog">
      <div class="modal-dialog">
        <div class="modal-content">
          <div class="modal-header">
            <button type="button" class="close" :class="[dirltr ? '' : 'rtl']" data-dismiss="modal" aria-hidden="true">
              &times;
            </button>

            <h4 class="modal-title">
              {{ $t('settings.api_token_create') }}
            </h4>
          </div>

          <div class="modal-body">
            <!-- Form Errors -->
            <error :errors="form.errors" />

            <!-- Create Token Form -->
            <form class="form-horizontal" role="form" @submit.prevent="store">
              <!-- Name -->
              <div class="form-group">
                <label for="create-token-name" class="col-md-4 col-form-label">
                  {{ $t('settings.api_token_name') }}
                </label>

                <div class="col-md-auto">
                  <input id="create-token-name" v-model="form.name" type="text" class="form-control" name="name" />
                </div>
              </div>

              <!-- Scopes -->
              <div v-if="scopes.length > 0" class="form-group">
                <label class="col-md-4 col-form-label">
                  {{ $t('settings.api_token_scopes') }}
                </label>

                <div class="col-md-auto">
                  <div v-for="scope in scopes" :key="scope.id">
                    <div class="checkbox">
                      <label>
                        <input type="checkbox"
                               :checked="scopeIsAssigned(scope.id)"
                               @click="toggleScope(scope.id)"
                        />

                        {{ scope.id }}
                      </label>
                    </div>
                  </div>
                </div>
              </div>
            </form>
          </div>

          <!-- Modal Actions -->
          <div class="modal-footer">
            <button type="button" class="btn btn-default" data-dismiss="modal">
              {{ $t('app.close') }}
            </button>

            <button type="button" class="btn btn-primary" @click="store">
              {{ $t('app.create') }}
            </button>
          </div>
        </div>
      </div>
    </div>

    <!-- Access Token Modal -->
    <div id="modal-access-token" class="modal fade" tabindex="-1" role="dialog">
      <div class="modal-dialog">
        <div class="modal-content">
          <div class="modal-header">
            <button type="button" class="close" :class="[dirltr ? '' : 'rtl']" data-dismiss="modal" aria-hidden="true">
              &times;
            </button>

            <h4 class="modal-title">
              {{ $t('settings.api_token_title') }}
            </h4>
          </div>

          <div class="modal-body">
            <p>{{ $t('settings.api_token_help') }}</p>

            <div class="access-key">
              <pre><code>{{ accessToken }}</code></pre>
            </div>
          </div>

          <!-- Modal Actions -->
          <div class="modal-footer">
            <button type="button" class="btn btn-default" data-dismiss="modal">
              {{ $t('app.close') }}
            </button>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
import Error from '../partials/Error.vue';

export default {

  components: {
    Error
  },

  data() {
    return {
      accessToken: null,

      tokens: [],
      scopes: [],

      form: {
        name: '',
        scopes: [],
        errors: []
      },
    };
  },

  computed: {
    dirltr() {
      return this.$root.htmldir == 'ltr';
    }
  },

  mounted() {
    this.prepareComponent();
  },

  methods: {
    prepareComponent() {
      this.getTokens();
      this.getScopes();

      $('#modal-create-token').on('shown.bs.modal', () => {
        $('#create-token-name').focus();
      });
    },

    /**
      * Get all of the personal access tokens for the user.
      */
    getTokens() {
      axios.get('oauth/personal-access-tokens')
        .then(response => {
          this.tokens = response.data;
        });
    },

    /**
      * Get all of the available scopes.
      */
    getScopes() {
      axios.get('oauth/scopes')
        .then(response => {
          this.scopes = response.data;
        });
    },

    /**
      * Show the form for creating new tokens.
      */
    showCreateTokenForm() {
      $('#modal-create-token').modal('show');
    },

    /**
      * Create a new personal access token.
      */
    store() {
      this.accessToken = null;

      this.form.errors = [];

      axios.post('oauth/personal-access-tokens', this.form)
        .then(response => {
          this.form.name = '';
          this.form.scopes = [];
          this.form.errors = [];

          this.tokens.push(response.data.token);

          this.showAccessToken(response.data.accessToken);
        })
        .catch(error => {
          if (typeof error.response.data === 'object') {
            this.form.errors = _.flatten(_.toArray(error.response.data));
          } else {
            this.form.errors = [this.$t('app.error_try_again')];
          }
        });
    },

    /**
      * Toggle the given scope in the list of assigned scopes.
      */
    toggleScope(scope) {
      if (this.scopeIsAssigned(scope)) {
        this.form.scopes = _.reject(this.form.scopes, s => s == scope);
      } else {
        this.form.scopes.push(scope);
      }
    },

    /**
      * Determine if the given scope has been assigned to the token.
      */
    scopeIsAssigned(scope) {
      return _.indexOf(this.form.scopes, scope) >= 0;
    },

    /**
      * Show the given access token to the user.
      */
    showAccessToken(accessToken) {
      $('#modal-create-token').modal('hide');

      this.accessToken = accessToken;

      $('#modal-access-token').modal('show');
    },

    /**
      * Revoke the given token.
      */
    revoke(token) {
      axios.delete('oauth/personal-access-tokens/' + token.id)
        .then(response => {
          this.getTokens();
        });
    }
  }
};
</script>
